package cn.charlotte.pit.listener;

import cn.charlotte.pit.ThePit;
import cn.charlotte.pit.event.PotionAddEvent;
import cn.charlotte.pit.events.impl.major.RedVSBlueEvent;
import cn.charlotte.pit.util.MaterialConvert;
import cn.charlotte.pit.util.item.ItemBuilder;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.mojang.datafixers.util.Pair;
import lombok.SneakyThrows;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import java.lang.reflect.Field;

/**
 * @Author: EmptyIrony
 * @Date: 2021/2/4 14:56
 */
public class PacketListener extends PacketAdapter {

    public PacketListener() {
        super(ThePit.getInstance(), PacketType.Play.Server.ENTITY_EQUIPMENT, PacketType.Play.Server.ENTITY_EFFECT);
    }

    @Override
    @SneakyThrows
    public void onPacketSending(PacketEvent event) {
        final Packet packet = (Packet) event.getPacket().getHandle();
        final Player player = event.getPlayer();

        if (packet instanceof ClientboundSetEquipmentPacket equipment) {
            boolean shouldSet = false;
            ItemStack material = null;
            if ("red_vs_blue".equals(ThePit.getInstance().getEventFactory().getActiveEpicEventName())) {
                for (Pair<EquipmentSlot, ItemStack> slot : equipment.getSlots()) {
                    if (slot.getFirst().equals(EquipmentSlot.HEAD)) {
                        RedVSBlueEvent activeEpicEvent = (RedVSBlueEvent) ThePit.getInstance().getEventFactory().getActiveEpicEvent();
                        for (Player target : Bukkit.getOnlinePlayers()) {
                            if (target.getEntityId() == equipment.getEntity()) {
                                shouldSet = true;
                                if (activeEpicEvent.getRedTeam().contains(target.getUniqueId())) {
                                    material = CraftItemStack.asNMSCopy(new ItemBuilder(MaterialConvert.WOOL[14]).build());
                                } else if (activeEpicEvent.getBlueTeam().contains(target.getUniqueId())) {
                                    material = CraftItemStack.asNMSCopy(new ItemBuilder(MaterialConvert.WOOL[11]).build());
                                }
                                break;
                            }
                        }
                    }
                }
                if (shouldSet) {
                    boolean finalShouldSet = shouldSet;
                    ItemStack finalMaterial = material;
                    equipment.getSlots().replaceAll(slot -> {
                        if (slot.getFirst().equals(EquipmentSlot.HEAD) && finalShouldSet) {
                            return new Pair<>(EquipmentSlot.HEAD, finalMaterial);
                        }
                        return slot;
                    });
                }
            }
        } else if (packet instanceof ClientboundUpdateMobEffectPacket mobEffectPacket) {
            final Integer entityId = mobEffectPacket.getEntityId();
            if (player.getEntityId() != entityId) return;

            final PotionEffectType potion = CraftPotionEffectType.minecraftHolderToBukkit(mobEffectPacket.getEffect());
            final Integer level = mobEffectPacket.getEffectAmplifier();
            final Integer duration = mobEffectPacket.getEffectDurationTicks();
            final boolean hide = !mobEffectPacket.isEffectVisible();

            Bukkit.getScheduler().runTaskLater(ThePit.getInstance(), () -> {
                PotionAddEvent potionEvent = new PotionAddEvent(player, new PotionEffect(potion, duration, level, hide));
                potionEvent.callEvent();

                if (potionEvent.isCancelled()) {
                    Bukkit.getScheduler().runTaskLater(ThePit.getInstance(), () -> {
                        player.removePotionEffect(potion);
                    }, 1L);
                }
            }, 1L);
        }
    }
}
